
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CoreCms.Net.Auth.Policys;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.FromBody;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.DTO;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using NETCore.Encrypt;
using SqlSugar;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinUserInfoBatchGetRequest.Types;


namespace CoreCms.Net.Services;

/// <summary>
/// 用户表 接口实现
/// </summary>
public class CoreCmsUserServices : BaseServices<CoreCmsUser>, ICoreCmsUserServices
{
    private readonly ICoreCmsUserRepository _dal;
    private readonly ICoreCmsUserBalanceServices _userBalanceServices;
    private readonly ICoreCmsSettingServices _settingServices;
    private readonly ICoreCmsUserPointLogServices _userPointLogServices;
    private readonly ICoreCmsSmsServices _smsServices;
    private readonly ICoreCmsUserWeChatInfoServices _userWeChatInfoServices;
    private readonly ICoreCmsUserGradeServices _userGradeServices;
    private readonly ICoreCmsUserLogServices _userLogServices;

    private readonly IServiceProvider _serviceProvider;

    private readonly IUnitOfWork _unitOfWork;
    private readonly PermissionRequirement _permissionRequirement;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ICoreCmsBillPaymentsServices _billPaymentsServices;
    private readonly ICoreCmsDistributionGradeRepository _distributionGradeRepository;
    private readonly ICoreCmsDistributionRepository _distributionRepository;

    private readonly ICoreCmsPromotionServices _coreCmsPromotionServices;
    private readonly ICoreCmsCouponServices _coreCmsCouponServices;
    private readonly ICoreCmsAliPayUserInfoServices _aliPayUserInfoServices;


    public CoreCmsUserServices(IUnitOfWork unitOfWork
        , ICoreCmsUserRepository dal
        , ICoreCmsUserBalanceServices userBalanceServices
        , ICoreCmsSettingServices settingServices
        , ICoreCmsUserPointLogServices userPointLogServices, ICoreCmsSmsServices smsServices,
        ICoreCmsUserWeChatInfoServices userWeChatInfoServices, ICoreCmsUserGradeServices userGradeServices,
        PermissionRequirement permissionRequirement, IHttpContextAccessor httpContextAccessor,
        ICoreCmsUserLogServices userLogServices, IServiceProvider serviceProvider,
        ICoreCmsBillPaymentsServices billPaymentsServices, ICoreCmsDistributionGradeRepository distributionGradeRepository, ICoreCmsDistributionRepository distributionRepository, ICoreCmsPromotionServices coreCmsPromotionServices, ICoreCmsCouponServices coreCmsCouponServices, ICoreCmsAliPayUserInfoServices aliPayUserInfoServices)
    {
        _dal = dal;
        BaseDal = dal;
        _unitOfWork = unitOfWork;
        _userBalanceServices = userBalanceServices;
        _settingServices = settingServices;
        _userPointLogServices = userPointLogServices;
        _smsServices = smsServices;
        _userWeChatInfoServices = userWeChatInfoServices;
        _userGradeServices = userGradeServices;
        _permissionRequirement = permissionRequirement;
        _httpContextAccessor = httpContextAccessor;
        _userLogServices = userLogServices;
        _serviceProvider = serviceProvider;
        _billPaymentsServices = billPaymentsServices;
        _distributionGradeRepository = distributionGradeRepository;
        _distributionRepository = distributionRepository;
        _coreCmsPromotionServices = coreCmsPromotionServices;
        _coreCmsCouponServices = coreCmsCouponServices;
        _aliPayUserInfoServices = aliPayUserInfoServices;
    }


    #region 更新余额

    /// <summary>
    /// 更新余额
    /// </summary>
    /// <param name="id"></param>
    /// <param name="money"></param>
    /// <param name="memo"></param>
    /// <returns></returns>
    public async Task<AdminUiCallBack> UpdateBalance(int id, decimal money, string memo)
    {
        var jm = new AdminUiCallBack();

        var model = await _dal.QueryByIdAsync(id);
        if (model == null)
        {
            jm.msg = "不存在此信息";
            return jm;
        }

        var newMoney = model.balance + money;
        var up = await _dal.UpdateAsync(p => new CoreCmsUser() { balance = newMoney }, p => p.id == id);
        if (up)
        {
            var balance = new CoreCmsUserBalance();
            balance.type = (int)GlobalEnumVars.UserBalanceSourceTypes.Admin;
            balance.userId = model.id;
            balance.balance = newMoney;
            balance.createTime = DateTime.Now;
            balance.memo = !string.IsNullOrEmpty(memo) ? memo : UserHelper.GetMemo(balance.type, money);
            balance.money = money;
            balance.sourceId = GlobalEnumVars.UserBalanceSourceTypes.Admin.ToString();

            jm.code = await _userBalanceServices.InsertAsync(balance) > 0 ? 0 : 1;
        }

        jm.msg = jm.code == 0 ? GlobalConstVars.EditSuccess : GlobalConstVars.EditFailure;

        return jm;
    }

    #endregion

    #region 更新积分

    /// <summary>
    /// 更新积分
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public async Task<AdminUiCallBack> UpdatePiont(FMUpdateUserPoint entity)
    {
        var jm = new AdminUiCallBack();

        var model = await _dal.QueryByIdAsync(entity.id);
        if (model == null)
        {
            jm.msg = "不存在此信息";
            return jm;
        }

        var newPoint = model.point + entity.point;
        var up = await _dal.UpdateAsync(p => new CoreCmsUser() { point = newPoint }, p => p.id == entity.id);
        if (up)
        {
            var point = new CoreCmsUserPointLog();
            point.userId = model.id;
            point.type = (int)GlobalEnumVars.UserPointSourceTypes.PointTypeAdminEdit;
            point.num = entity.point;
            point.balance = newPoint;
            point.remarks = entity.memo;
            point.createTime = DateTime.Now;

            jm.code = await _userPointLogServices.InsertAsync(point) > 0 ? 0 : 1;
        }

        jm.msg = jm.code == 0 ? GlobalConstVars.EditSuccess : GlobalConstVars.EditFailure;


        return jm;
    }

    #endregion

    #region 获取用户的积分

    /// <summary>
    /// 获取用户的积分
    /// </summary>
    /// <param name="userId">用户序列</param>
    /// <param name="orderMoney">订单金额</param>
    /// <param name="ids">货品序列</param>
    /// <param name="cartType">购物车类型</param>
    /// <returns></returns>
    public async Task<GetUserPointResult> GetUserPoint(int userId, decimal orderMoney, int[] ids, int cartType)
    {
        var dto = new GetUserPointResult();
        //1是2否
        var allConfigs = await _settingServices.GetConfigDictionaries();

        var pointSwitch = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.PointSwitch)
            .ObjectToInt(); //是否开启积分功能
        if (pointSwitch == 2)
        {
            dto.@switch = 2;
            return dto;
        }

        var user = await _dal.QueryByClauseAsync(p => p.id == userId);
        if (user != null)
        {
            dto.point = user.point;

            var pointExchangeModel = CommonHelper
                .GetConfigDictionary(allConfigs, SystemSettingConstVars.PointExchangeModel)
                .ObjectToInt(); //判断是全局模式还是单品模式
            if (pointExchangeModel == 1)
            {
                if (orderMoney != 0)
                {
                    //计算可用积分//订单积分使用比例
                    var ordersPointProportion = CommonHelper
                        .GetConfigDictionary(allConfigs, SystemSettingConstVars.OrdersPointProportion)
                        .ObjectToDecimal(10);
                    var proportion = Math.Round(ordersPointProportion / 100, 4);
                    //最多可以抵扣的金额
                    var maxPointDeductedMoney = Math.Round(orderMoney * proportion, 4);

                    //订单积分折现比例(多少积分可以折现1块钱)
                    var pointDiscountedProportion = CommonHelper
                        .GetConfigDictionary(allConfigs, SystemSettingConstVars.PointDiscountedProportion)
                        .ObjectToDecimal(100);
                    //计算需要多少积分
                    var needsPoint = maxPointDeductedMoney * pointDiscountedProportion;
                    //确定是否有那么多积分去抵扣比例计算出的能抵扣的钱
                    var availablePoint = needsPoint > user.point ? user.point : needsPoint;
                    dto.availablePoint = Convert.ToInt32(availablePoint);
                    dto.pointExchangeMoney = Math.Round(availablePoint / pointDiscountedProportion, 4);
                    //dto.pointExchangeMoney = dto.availablePoint / pointDiscountedProportion;
                }
            }
            else if (pointExchangeModel == 2)
            {
                using var container = _serviceProvider.CreateScope();

                var cartServices = container.ServiceProvider.GetService<ICoreCmsCartServices>();
                var productsServices = container.ServiceProvider.GetService<ICoreCmsProductsServices>();

                //获取购物车数据
                var cartProducts = await cartServices.QueryListByClauseAsync(p =>
                    p.type == cartType && p.userId == userId && ids.Contains(p.id));
                if (cartProducts.Any())
                {
                    //获取购物车货品序列
                    var cartIds = cartProducts.Select(p => p.productId).ToList();
                    //根据货品序列去找货品
                    var products = await productsServices.QueryListByClauseAsync(p => cartIds.Contains(p.id));
                    if (products.Any())
                    {
                        //可抵扣金额
                        decimal money = 0;
                        //迭代货品，获取到最高可优惠金额，进行累加
                        foreach (var item in products)
                        {
                            var numObj = cartProducts.Find(p => p.productId == item.id);
                            if (numObj != null) money += numObj.nums * item.pointsDeduction;
                        }

                        //计算抵扣这么多金额需要多少积分。
                        //订单积分折现比例(多少积分可以折现1块钱)
                        var pointDiscountedProportion = CommonHelper
                            .GetConfigDictionary(allConfigs, SystemSettingConstVars.PointDiscountedProportion)
                            .ObjectToInt(100);
                        //计算需要多少积分
                        var needsPoint = money * pointDiscountedProportion;

                        //确定是否有那么多积分去抵扣比例计算出的能抵扣的钱
                        var availablePoint = needsPoint > user.point ? 0 : needsPoint;
                        dto.availablePoint = Convert.ToInt32(availablePoint);

                        dto.pointExchangeMoney = user.point > needsPoint ? money : 0;
                    }
                }
            }
        }

        return dto;
    }

    #endregion

    #region 修改用户密码，如果用户之前没有密码，那么就不校验原密码

    /// <summary>
    ///   修改用户密码，如果用户之前没有密码，那么就不校验原密码
    /// </summary>
    public async Task<WebApiCallBack> ChangePassword(int userId, string newPwd, string password = "")
    {
        var jm = new WebApiCallBack();

        //修改密码验证原密码

        var user = await _dal.QueryByIdAsync(userId);
        if (user == null)
        {
            jm.msg = GlobalErrorCodeVars.Code10000;
            return jm;
        }

        if (!string.IsNullOrEmpty(user.passWord))
        {
            if (string.IsNullOrEmpty(password))
            {
                jm.msg = "请输入原密码!";
                return jm;
            }

            if (user.passWord != CommonHelper.EnPassword(password, user.createTime))
            {
                jm.msg = "原密码不正确!";
                return jm;
            }
        }

        if (string.IsNullOrEmpty(newPwd) || newPwd.Length < 6 || newPwd.Length > 16)
        {
            jm.msg = GlobalErrorCodeVars.Code11009;
            return jm;
        }

        var md5Pwd = CommonHelper.EnPassword(newPwd, user.createTime);

        if (!string.IsNullOrEmpty(user.passWord) && user.passWord == md5Pwd)
        {
            jm.msg = "原密码和新密码一样!";
            return jm;
        }

        var bl = await _dal.UpdateAsync(p => new CoreCmsUser() { passWord = md5Pwd, updataTime = DateTime.Now },
            p => p.id == userId);
        jm.status = bl;
        jm.msg = bl ? "密码修改成功!" : "密码修改失败!";
        return jm;
    }

    #endregion

    #region 绑定上级

    /// <summary>
    /// 绑定上级
    /// </summary>
    /// <param name="superiorId"></param>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<WebApiCallBack> SetMyInvite(int superiorId, int userId)
    {
        var jm = new WebApiCallBack() { msg = "填写邀请码失败" };

        jm.otherData = superiorId;

        //自己不能邀请自己
        if (userId == superiorId)
        {
            jm.msg = "自己不能邀请自己";
            return jm;
        }

        var user = await _dal.QueryByIdAsync(userId);
        if (user == null)
        {
            jm.msg = GlobalErrorCodeVars.Code10000;
            return jm;
        }

        if (user.parentId != 0)
        {
            jm.msg = "已有上级邀请，不能绑定其他的邀请";
            return jm;
        }

        var superior = await _dal.QueryByIdAsync(superiorId);
        if (superior == null)
        {
            jm.msg = "不存在这个邀请码";
            return jm;
        }

        if (superior.parentId == user.id)
        {
            jm.msg = "不允许双方互相设置为上级";
            return jm;
        }

        var flag = IsInvited(userId, superiorId);
        if (flag)
        {
            jm.msg = "不允许填写下级的邀请码";
            return jm;
        }

        var bl = await _dal.UpdateAsync(p => new CoreCmsUser() { parentId = superiorId }, p => p.id == userId);

        //增加上级积分
        if (bl)
        {
            var allConfigs = await _settingServices.GetConfigDictionaries();
            var inviterUserIntegral = CommonHelper
                .GetConfigDictionary(allConfigs, SystemSettingConstVars.InviterUserIntegral).ObjectToInt(); //是否开启积分功能
            if (inviterUserIntegral > 0)
                await _userPointLogServices.SetPoint(superiorId, inviterUserIntegral,
                    (int)GlobalEnumVars.UserPointSourceTypes.PointTypeInviterUser, "发展用户：" + userId + "赠送积分");
        }

        jm.status = bl;
        jm.msg = bl ? "填写邀请码成功!" : "填写邀请码失败!";
        return jm;
    }

    #endregion

    #region 获取我的上级邀请人

    /// <summary>
    /// 获取我的上级邀请人
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<WebApiCallBack> GetMyInvite(int userId)
    {
        var jm = new WebApiCallBack() { status = true };

        var user = await _dal.QueryByIdAsync(userId);
        if (user == null)
        {
            jm.msg = GlobalErrorCodeVars.Code10000;
            return jm;
        }

        if (user.parentId == 0)
        {
            jm.msg = "无上级邀请人";
            return jm;
        }

        var parentUser = await _dal.QueryByClauseAsync(p => p.id == user.parentId);
        if (parentUser != null)
            jm.data = new
            {
                nickname = parentUser.nickName,
                avatar = parentUser.avatarImage,
                mobile = UserHelper.FormatMobile(parentUser.mobile),
                ctime = parentUser.createTime
            };
        return jm;
    }


    /// <summary>
    ///     获取下级推广用户数量
    /// </summary>
    /// <param name="parentId">父类序列</param>
    /// <param name="type">1获取1级，其他为2级</param>
    /// <param name="thisMonth">当月</param>
    /// <returns></returns>
    public async Task<int> QueryChildCountAsync(int parentId, int type = 1, bool thisMonth = false)
    {
        return await _dal.QueryChildCountAsync(parentId, type, thisMonth);
    }

    /// <summary>
    /// 判断userId是否是pid的父节点或者祖父节点,如果是，就返回true，如果不是就返回false
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="pid"></param>
    /// <returns></returns>
    private bool IsInvited(int userId, int pid)
    {
        var info = _dal.QueryById(pid);
        if (info == null || info.parentId == 0)
        {
            return false;
        }
        else
        {
            if (info.parentId == userId)
                return true;
            else
                return IsInvited(userId, info.parentId);
        }
    }

    #endregion

    #region 忘记密码，找回密码

    /// <summary>
    /// 忘记密码，找回密码
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="newPwd"></param>
    /// <param name="cTime"></param>
    /// <returns></returns>
    public async Task<WebApiCallBack> ForgetPassword(string mobile, string code, string newPwd)
    {
        var jm = new WebApiCallBack();

        if (string.IsNullOrEmpty(code))
        {
            jm.msg = GlobalErrorCodeVars.Code10013;
            return jm;
        }

        var smsBool = await _smsServices.Check(mobile, code, "veri");
        if (!smsBool)
        {
            jm.msg = GlobalErrorCodeVars.Code10012;
            return jm;
        }

        var userInfo = await _dal.QueryByClauseAsync(p => p.mobile == mobile);
        if (userInfo == null)
        {
            jm.msg = "没有此手机号码";
            return jm;
        }

        return await EditPwd(userInfo.id, newPwd, userInfo.createTime);
    }

    #endregion

    #region 修改密码

    /// <summary>
    /// 修改密码
    /// </summary>
    /// <param name="userId">用户序列</param>
    /// <param name="newPwd">新密码</param>
    /// <param name="createTime">创建时间</param>
    /// <returns></returns>
    private async Task<WebApiCallBack> EditPwd(int userId, string newPwd, DateTime createTime)
    {
        var jm = new WebApiCallBack();

        if (string.IsNullOrEmpty(newPwd) || newPwd.Length < 6 || newPwd.Length > 16)
        {
            jm.msg = GlobalErrorCodeVars.Code11009;
            return jm;
        }

        var md5Pwd = CommonHelper.EnPassword(newPwd, createTime);
        var up = await _dal.UpdateAsync(p => new CoreCmsUser() { passWord = md5Pwd }, p => p.id == userId);
        if (!up)
        {
            jm.status = false;
            jm.msg = "密码修改失败";
            return jm;
        }

        jm.status = true;
        jm.msg = "密码修改成功";
        return jm;
    }

    #endregion

    #region 手机短信验证码登陆，同时兼有手机短信注册的功能，还有第三方账户绑定的功能

    /// <summary>
    /// 手机短信验证码登陆，同时兼有手机短信注册的功能，还有第三方账户绑定的功能
    /// </summary>
    /// <param name="entity">实体数据</param>
    /// <param name="loginType">登录方式(1普通,2短信,3微信小程序拉取手机号,4支付宝小程序拉取手机号)</param>
    /// <param name="platform"></param>
    /// <returns></returns>
    public async Task<WebApiCallBack> SmsLogin(FMComAccountCreate entity,
        int loginType = (int)GlobalEnumVars.LoginType.WeChatPhoneNumber,
        int platform = (int)GlobalEnumVars.CoreShopSystemCategory.Api)
    {
        var jm = new WebApiCallBack();

        if (string.IsNullOrEmpty(entity.mobile))
        {
            jm.msg = "请输入手机号码";
            return jm;
        }

        if (!CommonHelper.IsMobile(entity.mobile))
        {
            jm.msg = "请输入合法的手机号码";
            return jm;
        }

        if (loginType == (int)GlobalEnumVars.LoginType.Sms)
        {
            if (string.IsNullOrEmpty(entity.code))
            {
                jm.msg = "请输入验证码";
                return jm;
            }

            if (!await _smsServices.Check(entity.mobile, entity.code, "login"))
            {
                jm.msg = "短信验证码错误";
                return jm;
            }
        }

        var isReg = false;
        var userInfo = await _dal.QueryByClauseAsync(p => p.mobile == entity.mobile);
        if (userInfo == null)
        {
            isReg = true;
            userInfo = new CoreCmsUser();
            userInfo.userName = entity.mobile;
            userInfo.mobile = entity.mobile;
            userInfo.sex = 3;
            userInfo.isDelete = false;
            userInfo.balance = 0;
            userInfo.point = 0;
            userInfo.userWx = 0;
            userInfo.status = (int)GlobalEnumVars.UserStatus.正常;
            userInfo.createTime = DateTime.Now;

            //没有此用户，创建此用户
            if (!string.IsNullOrEmpty(entity.sessionAuthId) && loginType == (int)GlobalEnumVars.LoginType.WeChatPhoneNumber)
            {
                var wxUserInfo = await _userWeChatInfoServices.QueryByClauseAsync(p => p.openid == entity.sessionAuthId);
                if (wxUserInfo != null)
                {
                    if (string.IsNullOrEmpty(entity.avatar)) entity.avatar = wxUserInfo.avatar;
                    if (string.IsNullOrEmpty(entity.nickname)) entity.nickname = wxUserInfo.nickName;
                    userInfo.sex = wxUserInfo?.gender ?? 3;
                    userInfo.userWx = wxUserInfo?.id ?? 0;
                }
            }
            //else if (!string.IsNullOrEmpty(entity.sessionAuthId) && loginType == (int)GlobalEnumVars.LoginType.AliPhoneNumber)
            //{
            //    var aliUserInfo = await _aliPayUserInfoServices.QueryByClauseAsync(p => p.userId == entity.sessionAuthId || p.openId== entity.sessionAuthId);
            //    if (aliUserInfo != null)
            //    {
            //        //if (string.IsNullOrEmpty(entity.avatar)) entity.avatar = AliUserInfo.avatar;
            //        //if (string.IsNullOrEmpty(entity.nickname)) entity.nickname = wxUserInfo.nickName;
            //        //userInfo.sex = AliUserInfo?.gender ?? 3;
            //        userInfo.userWx = aliUserInfo?.id ?? 0;
            //    }
            //}

            var allConfigs = await _settingServices.GetConfigDictionaries();

            //如果没有头像和昵称，那么就取系统头像和昵称吧
            if (!string.IsNullOrEmpty(entity.avatar))
            {
                userInfo.avatarImage = entity.avatar;
            }
            else
            {
                var defaultImage = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.ShopDefaultImage);
                userInfo.avatarImage = defaultImage;
            }

            userInfo.nickName = !string.IsNullOrEmpty(entity.nickname) ? entity.nickname : UserHelper.FormatMobile(entity.mobile);

            if (entity.invitecode > 0)
            {
                var pid = UserHelper.GetUserIdByShareCode(entity.invitecode);
                var pInfo = await _dal.QueryByClauseAsync(p => p.id == pid);
                userInfo.parentId = pInfo != null ? pid : 0;
            }

            if (!string.IsNullOrEmpty(entity.password))
            {
                //判断密码是否符合要求
                if (entity.password.Length < 5 || entity.password.Length > 16)
                {
                    jm.msg = GlobalErrorCodeVars.Code11009;
                    return jm;
                }
                userInfo.passWord = CommonHelper.EnPassword(entity.password, userInfo.createTime);
            }
            else
            {
                userInfo.passWord = "";
            }

            //取默认的用户等级
            var userGradeInfo = await _userGradeServices.QueryByClauseAsync(p => p.isDefault == true);
            userInfo.grade = userGradeInfo?.id ?? 0;

            var userId = await _dal.InsertAsync(userInfo);

            if (userId > 0)
            {
                if (entity.invitecode > 0 && userInfo.parentId > 0)
                {
                    var inviterUserIntegral = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.InviterUserIntegral).ObjectToInt(); //是否开启积分功能
                    if (inviterUserIntegral > 0)
                        await _userPointLogServices.SetPoint(userInfo.parentId, inviterUserIntegral, (int)GlobalEnumVars.UserPointSourceTypes.PointTypeInviterUser, "发展用户：" + userId + "赠送积分");
                }

                //是否默认注册分销商
                var distributionType = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.DistributionType).ObjectToInt(); //是否默认注册分销商
                if (distributionType == (int)GlobalEnumVars.DistributionConditionType.RegOpen)
                {
                    var iData = new CoreCmsDistribution();
                    iData.userId = userId;

                    var disGradeModel = await _distributionGradeRepository.QueryByClauseAsync(p => p.isDefault == true);
                    iData.gradeId = disGradeModel?.id ?? 0;

                    iData.mobile = entity.mobile;
                    iData.name = userInfo.nickName;
                    iData.weixin = "";
                    iData.qq = "";
                    iData.verifyStatus = (int)GlobalEnumVars.DistributionVerifyStatus.VerifyYes;
                    iData.isDelete = false;
                    iData.createTime = DateTime.Now;

                    await _distributionRepository.InsertAsync(iData);
                }
            }
            else if (userId == 0)
            {
                jm.msg = GlobalErrorCodeVars.Code10000;
                return jm;
            }

            userInfo = await _dal.QueryByIdAsync(userId);

            var isAllowGiveCoupon = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.IsAllowGiveCoupon).ObjectToInt(); //是否赠送新人优惠券
            var selectGiveCoupon = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SelectGiveCoupon).ObjectToInt(); //选择注册赠送优惠券
            var giveCouponNumber = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.GiveCouponNumber).ObjectToInt(); //赠送优惠券数量

            if (userId > 0 && isAllowGiveCoupon == 1 && selectGiveCoupon > 0 && giveCouponNumber > 0)
            {
                var promotion = await _coreCmsPromotionServices.QueryByIdAsync(selectGiveCoupon);

                var dt = DateTime.Now;
                if (!promotion.isDel && promotion.isEnable && promotion.startTime < dt && promotion.endTime > dt)
                {
                    await _coreCmsCouponServices.AddData(userId, promotion.id, promotion, giveCouponNumber, "新人注册赠送");
                }
            }
        }
        else
        {
            //如果有这个账号的话，判断一下是不是传密码了，如果传密码了，就是注册，这里就有问题，因为已经注册过
            if (!string.IsNullOrEmpty(entity.password))
            {
                jm.msg = GlobalErrorCodeVars.Code11019;
                return jm;
            }
        }

        //判断是否是小程序里的微信登陆，如果是，就给他绑定微信账号
        if (!string.IsNullOrEmpty(entity.sessionAuthId) && loginType == (int)GlobalEnumVars.LoginType.WeChatPhoneNumber)
        {
            var updateAsync = await _userWeChatInfoServices.UpdateAsync(p => new CoreCmsUserWeChatInfo() { userId = userInfo.id }, p => p.openid == entity.sessionAuthId);
            if (updateAsync)
            {
                //多个微信可能同时授权一个号码登录。
                //如果已经存在微信用户(A)数据绑定了手机号码。
                //使用新微信(B)登录，同时又授权此手机号码绑定。
                //小程序内微信支付时候，因为登录的微信（B）与拉取手机号码绑定后获取到数据是（A）。
                //会导致微信数据报错（）

                //2023-05-05 屏蔽此代码，是为了让公众号，小程序实现多openid指向同一个账号，但是也存在问题，就是多了之后的解绑问题，应该做个登录设备管理。 
                //await _userWeChatInfoServices.UpdateAsync(p => new CoreCmsUserWeChatInfo() { userId = 0 }, p => p.openid != entity.sessionAuthId && p.userId == userInfo.id);
            }

            //如果是别的未绑定微信用户进来，则反向直接关联。
            var wxUserInfo = await _userWeChatInfoServices.QueryByClauseAsync(p => p.openid == entity.sessionAuthId);
            if (wxUserInfo != null)
            {
                await _dal.UpdateAsync(p => new CoreCmsUser() { userWx = wxUserInfo.id }, p => p.id == userInfo.id);
            }

        }
        else if (!string.IsNullOrEmpty(entity.sessionAuthId) && loginType == (int)GlobalEnumVars.LoginType.Sms)
        {
            var wxUserInfo = await _userWeChatInfoServices.QueryByClauseAsync(p => p.openid == entity.sessionAuthId && p.type == (int)GlobalEnumVars.UserAccountTypes.微信公众号);
            if (wxUserInfo != null)
            {
                await _userWeChatInfoServices.UpdateAsync(p => new CoreCmsUserWeChatInfo() { userId = userInfo.id }, p => p.openid == entity.sessionAuthId);
            }
        }
        else if (!string.IsNullOrEmpty(entity.sessionAuthId) && loginType == (int)GlobalEnumVars.LoginType.AliPhoneNumber)
        {
            await _aliPayUserInfoServices.UpdateAsync(p => new CoreCmsAliPayUserInfo() { userInfoId = userInfo.id }, p => p.openId == entity.sessionAuthId || p.userId == entity.sessionAuthId);
        }

        if (userInfo.status == (int)GlobalEnumVars.UserStatus.正常)
        {
            jm.status = true;
            jm.msg = "成功";
            jm.otherData = userInfo;

            if (platform == (int)GlobalEnumVars.CoreShopSystemCategory.Api)
            {
                var claims = new List<Claim>
                {
                    new(ClaimTypes.Name, userInfo.nickName),
                    new(JwtRegisteredClaimNames.Jti, userInfo.id.ToString()),
                    new(ClaimTypes.Expiration,
                        DateTime.Now.AddSeconds(_permissionRequirement.Expiration.TotalSeconds).ToString())
                };
                //用户标识
                var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
                identity.AddClaims(claims);

                //返回处理结果集
                var auth = JwtToken.BuildJwtToken(claims.ToArray(), _permissionRequirement);
                //对token进行非对称加密
                auth.token = EncryptProvider.AESEncrypt(auth.token, AppSettingsConstVars.JwtConfigSecretKey);

                jm.data = auth;
            }
            else
            {
                jm.data = userInfo;
            }

            //录入登录日志
            var log = new CoreCmsUserLog();
            log.userId = userInfo.id;
            log.state = isReg ? (int)GlobalEnumVars.UserLogTypes.注册 : (int)GlobalEnumVars.UserLogTypes.登录;
            log.ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null
                ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString()
                : "127.0.0.1";
            log.createTime = DateTime.Now;
            log.parameters =
                isReg ? GlobalEnumVars.UserLogTypes.注册.ToString() : GlobalEnumVars.UserLogTypes.登录.ToString();
            await _userLogServices.InsertAsync(log);
        }
        else
        {
            jm.msg = GlobalErrorCodeVars.Code11022;
            return jm;
        }

        return jm;
    }

    #endregion

    #region 根据条件查询分页数据

    /// <summary>
    ///     根据条件查询分页数据
    /// </summary>
    /// <param name="predicate">判断集合</param>
    /// <param name="orderByType">排序方式</param>
    /// <param name="pageIndex">当前页面索引</param>
    /// <param name="pageSize">分布大小</param>
    /// <param name="orderByExpression"></param>
    /// <returns></returns>
    public async Task<IPageList<CoreCmsUser>> QueryPageAsync(Expression<Func<CoreCmsUser, bool>> predicate,
        Expression<Func<CoreCmsUser, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
        int pageSize = 20)
    {
        return await _dal.QueryPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize);
    }

    #endregion

    #region 重写根据条件查询分页数据
    /// <summary>
    ///     重写根据条件查询分页数据
    /// </summary>
    /// <param name="predicate">判断集合</param>
    /// <param name="orderByType">排序方式</param>
    /// <param name="pageIndex">当前页面索引</param>
    /// <param name="pageSize">分布大小</param>
    /// <param name="orderByExpression"></param>
    /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
    /// <returns></returns>
    public async Task<IPageList<CoreCmsUser>> QueryPageAsyncNew(Expression<Func<CoreCmsUser, bool>> predicate,
        Expression<Func<CoreCmsUser, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
        int pageSize = 20, bool blUseNoLock = false)
    {
        return await _dal.QueryPageAsyncNew(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock);
    }
    #endregion

    #region 按天统计新会员

    /// <summary>
    /// 按天统计新会员
    /// </summary>
    /// <returns></returns>
    public async Task<List<StatisticsOut>> Statistics(int day)
    {
        return await _dal.Statistics(day);
    }

    #endregion

    #region 按天统计当天下单活跃会员

    /// <summary>
    /// 按天统计当天下单活跃会员
    /// </summary>
    /// <returns></returns>
    public async Task<List<StatisticsOut>> StatisticsOrder(int day)
    {
        return await _dal.StatisticsOrder(day);
    }

    #endregion

    #region 当关闭分销和代理的时候走个人邀请好友分佣

    /// <summary>
    /// 当关闭分销和代理的时候走个人邀请好友分佣
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    public async Task<WebApiCallBack> InviteCommission(string orderId)
    {
        using var container = _serviceProvider.CreateScope();
        var _orderServices = container.ServiceProvider.GetService<ICoreCmsOrderServices>();
        var _billPaymentsServices = container.ServiceProvider.GetService<ICoreCmsBillPaymentsServices>();


        var jm = new WebApiCallBack();
        var allConfigs = await _settingServices.GetConfigDictionaries();
        //分佣类型（1百分比/2固定金额）
        var commissionType = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CommissionType)
            .ObjectToInt(0);
        //一级佣金
        var commissionFirst = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CommissionFirst)
            .ObjectToDecimal(0);
        //二级佣金
        var commissionSecond = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CommissionSecond)
            .ObjectToDecimal(0);
        //三级佣金
        var commissionThird = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.CommissionFirst)
            .ObjectToDecimal(0);
        //是否开启三级分销(1开启，2未开启)
        var openDistribution = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.OpenDistribution)
            .ObjectToInt(0);
        //是否开启代理模块(1开启，2未开启)
        var isOpenAgent = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.IsOpenAgent)
            .ObjectToInt(0);

        //当分销模块和代理模块都关闭的情况下，才去计算邀请好友的操作。
        if (openDistribution != 2 || isOpenAgent != 2) return jm;
        var order = await _orderServices.QueryByClauseAsync(p =>
            p.orderId == orderId && p.status == (int)GlobalEnumVars.OrderStatus.Complete);
        if (order == null)
        {
            jm.msg = "订单查询失败";
            return jm;
        }

        var user = await _dal.QueryByClauseAsync(p => p.id == order.userId, true);

        // 获取付款单，我们只拿付款单的实际金额去计算，不用订单的金额。这样直接不用去计算优惠了，只看用户付了多少。从上面提佣金出来。
        var billPayments = await _billPaymentsServices.QueryByClauseAsync(p =>
            p.sourceId == orderId && p.status == (int)GlobalEnumVars.BillPaymentsStatus.Payed);
        if (billPayments.money <= 0) return jm;
        {
            //1级佣金
            var commissionLevel1 = commissionType == (int)GlobalEnumVars.InviteCommissionType.CommissionTypeFixed
                ? commissionFirst
                : Math.Round(commissionFirst * billPayments.money / 100, 2);
            //2级佣金
            var commissionLevel2 = commissionType == (int)GlobalEnumVars.InviteCommissionType.CommissionTypeFixed
                ? commissionSecond
                : Math.Round(commissionSecond * billPayments.money / 100, 2);
            //3级佣金
            var commissionLevel3 = commissionType == (int)GlobalEnumVars.InviteCommissionType.CommissionTypeFixed
                ? commissionThird
                : Math.Round(commissionThird * billPayments.money / 100, 2);


            //下面存储就不做递归了，三层直接判断了
            if (user.parentId <= 0) return jm;
            var parentLevel1 = await _dal.QueryByClauseAsync(p => p.id == user.parentId, true);
            if (parentLevel1 == null) return jm;
            {
                //钱挪到会员余额里面
                await _userBalanceServices.Change(user.parentId,
                    (int)GlobalEnumVars.UserBalanceSourceTypes.Distribution, commissionLevel1, orderId);
                if (parentLevel1.parentId <= 0) return jm;
                var parentLevel2 = await _dal.QueryByClauseAsync(p => p.id == parentLevel1.parentId, true);
                //钱挪到会员余额里面
                await _userBalanceServices.Change(parentLevel1.parentId,
                    (int)GlobalEnumVars.UserBalanceSourceTypes.Distribution, commissionLevel2, orderId);
                if (parentLevel2.parentId <= 0) return jm;
                {
                    var parentLevel3 = await _dal.QueryByClauseAsync(p => p.id == parentLevel2.parentId, true);
                    if (parentLevel3 != null)
                        //钱挪到会员余额里面
                        await _userBalanceServices.Change(parentLevel2.parentId,
                            (int)GlobalEnumVars.UserBalanceSourceTypes.Distribution, commissionLevel3, orderId);
                }
            }
        }
        return jm;
    }

    #endregion

    public async Task<string> GetLastAccount()
    {
        var userInfo = _dal.Query()
            .OrderByDescending(item => item.number)
            .Where(item => item.number.StartsWith("HJ")
            && item.number.Length >= 8)
            .FirstOrDefault();
        if (userInfo == null)
        {
            return "HJ000001";
        }
        var num = await getAccount(userInfo.number, 0);
        if (num == 0)
        {
            throw new Exception("获取账号失败");
        }
        return $"HJ{num.ToString().PadLeft(6, '0')}";
    }
    private async Task<int> getAccount(string account, int count)
    {
        count += 1;
        var reg = new Regex(@"\d+");
        var str = reg.Match(account);
        int num = int.Parse(str.Value) + 1;
        var user = await _dal.QueryByClauseAsync(item => item.number == account);
        if (user != null)
        {
            if (count > 10)
            {
                return 0;
            }
            await getAccount(user.number, count);
        }
        return num;
    }
    /// <summary>
    /// 根据会员组获取会员id
    /// </summary>
    /// <returns></returns>
    public async Task<List<int>> GetUserIdsByGrade(int gradeId)
    {
        var ids = await _dal.GetUserIdsByGrade(gradeId);
        return ids;
    }

}